package com.dcjt.firehotcarpad.utils

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Matrix
import android.media.ExifInterface
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.widget.ImageView
import androidx.core.content.FileProvider
import com.bumptech.glide.Glide
import com.dcjt.firehotcarpad.manager.DataManager
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.ImageViewerPopupView
import com.lxj.xpopup.interfaces.OnSrcViewUpdateListener
import com.lxj.xpopup.interfaces.XPopupImageLoader
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*


/**
 * <p>文件描述：视频工具类
 * https://www.jianshu.com/p/bd308c8371dd<p>
 * <p>@author 烤鱼<p>
 * <p>@date 2020/2/14 0014 <p>
 * <p>@update 2020/2/14 0014<p>
 * <p>版本号：1<p>
 *
 */
object MediaUtils {
    const val MEDIA_TYPE_IMAGE = 1
    const val MEDIA_TYPE_VIDEO = 2

    var file: File? = null

    /**
     * Create a file Uri for saving an image or video
     */
    fun getOutputMediaFileUri(context: Context, type: Int): Uri? {
        val uri: Uri? = null
        //适配Android N
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            FileProvider.getUriForFile(
                context,
                context.applicationContext.packageName.toString() + ".provider",
                getOutputMediaFile(type)!!
            )
        } else {
            Uri.fromFile(getOutputMediaFile(type))
        }
    }

    /**
     * Create a File for saving an image or video
     */
    @SuppressLint("SimpleDateFormat")
    fun getOutputMediaFile(type: Int): File? { // To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
        val mediaStorageDir = File(
            Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES
            ), "image"
        )
        // This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                return null
            }
        }
        // Create a media file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val mediaFile: File
        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = File(
                mediaStorageDir.getPath() + File.separator.toString() +
                        "IMG_" + timeStamp + ".jpg"
            )
        } else if (type == MEDIA_TYPE_VIDEO) {
            mediaFile = File(
                mediaStorageDir.getPath() + File.separator.toString() +
                        "VID_" + timeStamp + ".mp4"
            )
        } else {
            return null
        }
        file = mediaFile
        return mediaFile
    }

    /**
     * 获取视频的第一帧图片
     */
    @SuppressLint("CheckResult")
    fun getImageForVideo(
        videoPath: String,
        listener: ((file: File?) -> Unit)?
    ) {

        Observable
            .create(ObservableOnSubscribe<String> { emitter -> emitter.onNext(videoPath) })
            .map {
                val mmr = MediaMetadataRetriever()
                if (videoPath.startsWith("http")) //获取网络视频第一帧图片
                    mmr.setDataSource(videoPath, HashMap()) else  //本地视频
                    mmr.setDataSource(videoPath)
                val bitmap = mmr.frameAtTime
                //保存图片
                val f = getOutputMediaFile(MEDIA_TYPE_IMAGE)
                if (f?.exists() == true) {
                    f.delete()
                }
                try {
                    val newbitmap = resizeBitmap(480f, 480f, bitmap)
                    val out = FileOutputStream(f)
                    newbitmap.compress(Bitmap.CompressFormat.JPEG, 60, out)
                    out.flush()
                    out.close()
                } catch (e: FileNotFoundException) {
                    e.printStackTrace()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                mmr.release()
                return@map f
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                listener?.invoke(it)
            }

    }


    fun resizeBitmap(newWidth: Float, newHeight: Float, bitmap: Bitmap): Bitmap {
        val matrix = Matrix()
        matrix.postScale(
            newWidth / bitmap.width,
            newHeight / bitmap.height
        )
        return Bitmap.createBitmap(
            bitmap, 0, 0, bitmap.width,
            bitmap.height, matrix, true
        )
    }


    /**
     * 读取图片的旋转的角度
     *
     * @param path 图片绝对路径
     * @return 图片的旋转角度
     */
    fun getBitmapDegree(path: String?): Int {
        var degree = 0
        try { // 从指定路径下读取图片，并获取其EXIF信息
            val exifInterface = ExifInterface(path)
            // 获取图片的旋转信息
            val orientation = exifInterface.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL
            )
            when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
                ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
                ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return degree
    }


    /**
     * 旋转图片，使图片保持正确的方向。
     *
     * @param bitmap  原始图片
     * @param degrees 原始图片的角度
     * @return Bitmap 旋转后的图片
     */
    fun rotateBitmap(bitmap: Bitmap?, degrees: Int): Bitmap? {
        if (degrees == 0 || null == bitmap) {
            return bitmap
        }
        val matrix = Matrix()
        matrix.setRotate(
            degrees.toFloat(),
            bitmap.width / 2.toFloat(),
            bitmap.height / 2.toFloat()
        )
        val bmp =
            Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
        bitmap.recycle()
        return bmp
    }

    /**
     * 预览单张图片
     * @param context 当前UI的上下文对象
     * @param path 图片地址（项目中一般是发送相对地址）
     * @param imgView 图片动画起点
     * @param baseUrl 图片的服务器地址 图片为绝对地址时传空字符串。项目中一般不用传
     */
    fun showSingleImage(context: Context,path: String,imgView:ImageView?,baseUrl:String = DataManager.getInstance().appConfigEntity.appServerUrl.logUrl +"/"){
        XPopup.Builder(context).asImageViewer(imgView,path, getImageLoader(baseUrl))
            .isShowSaveButton(false).show()
    }

    /**
     * 预览多张图片
     * @param context 当前UI的上下文对象
     * @param pathList 图片地址集合
     * @param imgView 图片动画起点
     * @param changeCallback 图片滑动回调
     * @param position 显示的序号
     * @param baseUrl 图片的服务器地址 图片为绝对地址时传空字符串。项目中一般不用传
     */
    fun showMultiImage(context: Context,pathList: List<String>,imgView:ImageView?,changeCallback:((ImageViewerPopupView,Int) -> Unit),position:Int = 0,baseUrl:String = DataManager.getInstance().appConfigEntity.appServerUrl.logUrl +"/"){
        XPopup.Builder(context).asImageViewer(imgView,position,pathList,changeCallback,getImageLoader(baseUrl))
            .isShowSaveButton(false).show()
    }

    private fun getImageLoader(baseUrl:String = ""):XPopupImageLoader{
        return object : XPopupImageLoader {
            override fun loadImage(position: Int,uri: Any,imageView: ImageView) {
                Glide.with(imageView).load(baseUrl + uri).into(imageView)
            }

            override fun getImageFile(context: Context, uri: Any): File? {
                try {
                    return Glide.with(context).downloadOnly().load(uri)
                        .submit()
                        .get()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
                return null
            }

        }
    }
}